{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################### 函数递归 ###################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 函数递归调用其实就是自己调用自己，关键点只要考虑什么时候跳出即可(没有跳出就是死循环)\n",
    "# 阶乘案例 n!\n",
    "def factorial(n):\n",
    "    if n==1:\n",
    "        return n #跳出\n",
    "    elif n>1:\n",
    "        return n*factorial(n-1) #规律公式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "24\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "print(factorial(4))\n",
    "print(factorial(-4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 利用切片操作，实现一个trim()函数，去除字符串首尾的空格\n",
    "# 跳出点==> 第一个字符和最后一个字符不是空格\n",
    "def my_trim(input_str):\n",
    "    if input_str[0] != \" \" and input_str[-1] != \" \":\n",
    "        return input_str\n",
    "    elif input_str[0]==\" \":\n",
    "        return my_trim(input_str[1:])#从第二个到最后一个字符\n",
    "    elif input_str[-1]==\" \":\n",
    "        return my_trim(input_str[:-1])#从第一个到倒数第二个(end_index取不到)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "我去\n",
      "我去\n",
      "我去\n"
     ]
    }
   ],
   "source": [
    "print(my_trim(\"我去  \"))\n",
    "print(my_trim(\"  我去\"))\n",
    "print(my_trim(\"  我去  \"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################### 匿名函数 ###################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Python对匿名函数的支持有限，只有一些简单的情况下可以使用匿名函数\n",
    "# lambda 参数: 表达式\n",
    "# 来个简单求和案例:\n",
    "sum=lambda a,b: a+b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(1,2) #调用一下看看(有点js的感觉,函数可以直接赋值给变量,然后直接用)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 来个实际案例,还记得list的排序吗?\n",
    "# 这次按照指定key排序(有点 SQL 里面 order by 的感觉)\n",
    "data_list=[\n",
    "    {\"name\":\"a张三\",\"age\":21},\n",
    "    {\"name\":\"b李四\",\"age\":23},\n",
    "    {\"name\":\"a王五\",\"age\":22}]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on built-in function sort:\n",
      "\n",
      "sort(...) method of builtins.list instance\n",
      "    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(data_list.sort)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'name': 'a张三', 'age': 21}, {'name': 'a王五', 'age': 22}, {'name': 'b李四', 'age': 23}]\n",
      "[{'name': 'a张三', 'age': 21}, {'name': 'a王五', 'age': 22}, {'name': 'b李四', 'age': 23}]\n"
     ]
    }
   ],
   "source": [
    "# 按照age排序\n",
    "data_list.sort(key=lambda x:x[\"age\"])\n",
    "print(data_list)\n",
    "\n",
    "# 按照name排序\n",
    "data_list.sort(key=lambda x:x[\"name\"])\n",
    "print(data_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 当函数的参数传递(有时候需要传一个匿名方法去函数中处理某些事情)\n",
    "def sum(a,b,func):\n",
    "   return func(a,b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "sum(1,2,lambda x,y: x+y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################### 全局变量 ###################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 有人可能会说，这个就太简单了，没啥好说的，(⊙o⊙)… Python还真需要说说\n",
    "a=100\n",
    "b=[1,2]\n",
    "\n",
    "def set_num(num):\n",
    "    num+=num\n",
    "\n",
    "set_num(a)\n",
    "set_num(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n",
      "[1, 2, 1, 2]\n"
     ]
    }
   ],
   "source": [
    "# 发现全局变量a木有被修改，而b修改了\n",
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "100\n"
     ]
    }
   ],
   "source": [
    "# 还是来个简单案例说明下吧～\n",
    "a=100\n",
    "\n",
    "def set_num(num):\n",
    "    a=200\n",
    "\n",
    "set_num(a)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "200\n"
     ]
    }
   ],
   "source": [
    "# 这是因为，python定义一个变量的写法不用加类型导致的(⊙﹏⊙) 所以函数里面a=200，python解释器就认为你\n",
    "# 定义了一个和a这个全局变量名字相同的局部变量，那怎么用呢？global来声明一下即可\n",
    "a=100\n",
    "\n",
    "def set_num(num):\n",
    "    global a\n",
    "    a=200\n",
    "\n",
    "set_num(a)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在函数中不使用global声明全局变量不能修改全局变量==>本质是不能修改全局变量的指向，即不能将全局变量指向新的数据\n",
    "# 对于不可变类型的全局变量来说，因其指向的数据不能修改，所以不使用global时无法修改全局变量\n",
    "# 对于可变类型的全局变量来说，因其指向的数据可以修改，所以不使用global时也可修改全局变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "####################### 验证系列 ###################################"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 之前很多资料说py3匿名函数里不能调用print函数,自己测试下\n",
    "# 定义一个无参匿名函数\n",
    "printf=lambda:print(\"I Love You\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "I Love You\n"
     ]
    }
   ],
   "source": [
    "printf()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 可变类型与不可变类型的变量分别作为函数参数的区别\n",
    "# 感到疑惑可以看之前的运算符扩展（https://www.cnblogs.com/dotnetcrazy/p/9155310.html#ext）\n",
    "def default_some_params(nums):\n",
    "    nums+=nums"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_num=1\n",
    "default_some_params(test_num)\n",
    "test_num"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 3, 4, 5, 1, 2, 3, 4, 5]"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test_list=list(range(1,6))\n",
    "default_some_params(test_list)\n",
    "test_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Python中函数参数是引用传递\n",
    "# 对于不可变类型，因变量不能修改，所以运算不会影响到变量自身\n",
    "# 而对于可变类型来说，函数体中的运算有可能会更改传入的参数变量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 函数名能不能重复的问题（能不能重载：具有不同的参数的类型或参数的个数）\n",
    "def test():\n",
    "    pass\n",
    "\n",
    "def test(a,b):\n",
    "    return a+b"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "3"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "test(1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "ename": "TypeError",
     "evalue": "test() missing 2 required positional arguments: 'a' and 'b'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[0;32m<ipython-input-29-023d21616394>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mtest\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m#前一个直接被后一个覆盖掉了\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;31mTypeError\u001b[0m: test() missing 2 required positional arguments: 'a' and 'b'"
     ]
    }
   ],
   "source": [
    "test() #前一个直接被后一个覆盖掉了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 来两个有趣的扩展：\n",
    "# 1.交换两个数熟悉吧，编程第一课，除了用第三变量 或者 两数相加减 实现外，Python还有一种新方式：\n",
    "a,b=2,3\n",
    "a,b=b,a"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "print(a)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "请输入：print(\"厉害\")\n",
      "print(\"厉害\")\n",
      "厉害\n"
     ]
    }
   ],
   "source": [
    "# 2.eval（和js里面的eval差不多）：\n",
    "input_str=input(\"请输入：\")\n",
    "print(input_str)\n",
    "eval(input_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
